﻿using System.Collections.Generic;
using System.Collections;
using UnityEngine;

public struct Location
{
    public int row;
    public int col;

    public Location(int r,int c)
    {
        row = r;
        col = c;
    }
}

// 游戏核心算法类
public class GameCore
{
    private int[,] map;//地图对应值数组
    private List<Location> emptyLocList; //空位置的对应的点位
    private int[,] originalMap;//每次移动前保存的地图
    private int[] mergeArray;//要合并的一行或一列数组
    private int[] removeZeroArray;//去零数组
    public bool isChange = false;//地图是否改变
    public int score = 0;


    public int[,] Map
    {
        get { return map; }
    }
   
    public GameCore()
    {
        map = new int[4, 4];
        emptyLocList = new List<Location>(16);
        originalMap = new int[4, 4];
        mergeArray = new int[4];
        removeZeroArray = new int[4];
    }

    /// 计算空格子
    private void CalculateEmpty()
    {
        emptyLocList.Clear();
        for (int r = 0; r < map.GetLength(0); r++)
        {
            for (int c = 0; c < map.GetLength(1); c++)
            {
                if (map[r, c] == 0)
                {
                    emptyLocList.Add(new Location(r, c));
                }
            }
        }
    }

    //生成新数字
    public void GenerateNumber(out Location loc, out int newNumber)
    {
        CalculateEmpty();

        if (emptyLocList.Count > 0)
        {          
            int index = Random.Range(0, emptyLocList.Count); //0,15
            loc = emptyLocList[index]; //有空位置的list  3
            newNumber = map[loc.row, loc.col] = Random.Range(0, 10) == 1 ? 4 : 2;
            emptyLocList.RemoveAt(index);
        }
        else
        {
            newNumber = -1;
            loc = new Location(-1, -1);
        }
    }

    //去零数组
    private void RemoveZero()
    {
        System.Array.Clear(removeZeroArray, 0, 4);

        int index = 0;
        foreach (var item in mergeArray)
        {
            if (item != 0)
                removeZeroArray[index++] = item; //1
        }

        removeZeroArray.CopyTo(mergeArray, 0);
    }

    // 合并数字
    private void Merge()
    {
        RemoveZero(); 
        for (int i = 0; i < mergeArray.Length - 1; i++)
        {
            if (mergeArray[i] != 0 && mergeArray[i] == mergeArray[i + 1])
            {
                mergeArray[i] += mergeArray[i + 1];
                mergeArray[i + 1] = 0;
                score += mergeArray[i];
                EventMgr.instance.Emit("UpdateCurScore", score);
            }
        }

        RemoveZero(); 
    }

    // 上移
    private void MoveUp()
    {
        for (int c = 0; c < map.GetLength(1); c++)
        {
            for (int r = 0; r < map.GetLength(0); r++)
                mergeArray[r] = map[r, c];

            Merge();

            for (int r = 0; r < map.GetLength(0); r++)
                map[r, c] = mergeArray[r];
        }
    }

    // 下移
    private void MoveDown()
    {
        for (int c = 0; c < map.GetLength(1); c++)
        {
            for (int r = map.GetLength(0) - 1; r >= 0; r--)
            {
                mergeArray[3 - r] = map[r, c];
            }

            Merge();

            for (int r = map.GetLength(0) - 1; r >= 0; r--)
            {
                map[r, c] = mergeArray[3 - r];
            }
        }
    }

    // 左移
    private void MoveLeft()
    {
        for (int r = 0; r < 4; r++)
        {
            for (int c = 0; c < 4; c++)
                mergeArray[c] = map[r, c];

            Merge();

            for (int c = 0; c < 4; c++)
                map[r, c] = mergeArray[c];
        }
    }

    // 右移
    private void MoveRight()
    {
        for (int r = 0; r < 4; r++)
        {
            for (int c = 3; c >= 0; c--)
                mergeArray[3 - c] = map[r, c];

            Merge();

            for (int c = 3; c >= 0; c--)
                map[r, c] = mergeArray[3 - c];
        }
    }

    // 移动
    public void Move(MoveDirection direction)
    {
        //移动前记录Map   
        #region 省略
        //for (int r = 0; r < Map.GetLength(0); r++)
        //{
        //    for (int c = 0; c < Map.GetLength(1); c++)
        //    {
        //        originalMap[r, c] = Map[r, c];
        //    }
        //}
        #endregion
        System.Array.Copy(map, originalMap, map.Length);

        switch (direction)
        {
            case MoveDirection.UP:
                MoveUp();
                break;
            case MoveDirection.DOWN:
                MoveDown();
                break;
            case MoveDirection.LEFT:
                MoveLeft();
                break;
            case MoveDirection.RIGHT:
                MoveRight();
                break;
        }
        //移动后对比 
        CheckMapChange();
    }


    // 检测地图是否发生变化
    private void CheckMapChange()
    {
        for (int r = 0; r < map.GetLength(0); r++)
        {
            for (int c = 0; c < map.GetLength(1); c++)
            {
                if (map[r, c] != originalMap[r, c])
                {
                    isChange = true; //发生改变
                    return;
                }
            }
        }
    }

    // 游戏是否结束
    public bool IsOver()
    {
        if (emptyLocList.Count > 0)
        {
            return false;
        }

        #region 省略

        //水平
        //for (int r = 0; r < 4; r++)
        //{
        //    for (int c = 0; c < 3; c++)
        //    {
        //        if (map[r, c] == map[r, c + 1])
        //            return false;
        //    } 
        //}
        ////垂直
        //for (int c = 0; c < 4; c++)
        //{
        //    for (int r = 0; r < 3; r++)
        //    {
        //        if (map[r, c] == map[r + 1, c])
        //            return false;
        //    } 
        //}

        #endregion

        for (int r = 0; r < 4; r++)
        {
            for (int c = 0; c < 3; c++)
            {
                if (map[r, c] == map[r, c + 1] || map[c, r] == map[c + 1, r])
                {
                    return false;
                }
            }
        }
        return true; //游戏结束 
    }
}
